G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
+typedef enum {
+ SHELL_APP_INFO_TYPE_ENTRY,
+ SHELL_APP_INFO_TYPE_DESKTOP_FILE
+} ShellAppInfoType;
+
+struct _ShellAppInfo {
+ ShellAppInfoType type;
+
+ /* We need this for two reasons. First, GKeyFile doesn't have a refcount.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=590808
+ *
+ * But more generally we'll always need it so we know when to free this
+ * structure (short of weak references on each item).
+ */
+ guint refcount;
+
+ GMenuTreeItem *entry;
+
+ GKeyFile *keyfile;
+ char *keyfile_path;
+};
+
ShellAppInfo*
shell_app_info_ref (ShellAppInfo *info)
{
- return gmenu_tree_item_ref ((GMenuTreeItem*)info);
+ info->refcount++;
+ return info;
}
void
shell_app_info_unref (ShellAppInfo *info)
{
- gmenu_tree_item_unref ((GMenuTreeItem *)info);
+ if (--info->refcount > 0)
+ return;
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ gmenu_tree_item_unref (info->entry);
+ break;
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ g_key_file_free (info->keyfile);
+ g_free (info->keyfile_path);
+ break;
+ }
+ g_slice_free (ShellAppInfo, info);
+}
+
+static ShellAppInfo *
+shell_app_info_new_from_tree_item (GMenuTreeItem *item)
+{
+ ShellAppInfo *info;
+
+ if (!item)
+ return NULL;
+
+ info = g_slice_alloc (sizeof (ShellAppInfo));
+ info->type = SHELL_APP_INFO_TYPE_ENTRY;
+ info->refcount = 1;
+ info->entry = gmenu_tree_item_ref (item);
+ return info;
+}
+
+static ShellAppInfo *
+shell_app_info_new_from_keyfile_take_ownership (GKeyFile *keyfile,
+ const char *path)
+{
+ ShellAppInfo *info;
+
+ info = g_slice_alloc (sizeof (ShellAppInfo));
+ info->type = SHELL_APP_INFO_TYPE_DESKTOP_FILE;
+ info->refcount = 1;
+ info->keyfile = keyfile;
+ info->keyfile_path = g_strdup (path);
+ return info;
}
static gpointer
{
case GMENU_TREE_ITEM_ENTRY:
{
- apps = g_slist_prepend (apps, item);
+ ShellAppInfo *app = shell_app_info_new_from_tree_item (item);
+ apps = g_slist_prepend (apps, app);
}
break;
case GMENU_TREE_ITEM_DIRECTORY:
GMenuTreeDirectory *dir = (GMenuTreeDirectory*)item;
apps = gather_entries_recurse (monitor, apps, dir);
}
- gmenu_tree_item_unref (item);
break;
default:
- gmenu_tree_item_unref (item);
break;
}
+ gmenu_tree_item_unref (item);
}
g_slist_free (contents);
{
ShellAppInfo *info = iter->data;
if (ref)
- gmenu_tree_item_ref ((GMenuTreeItem*) info);
+ shell_app_info_ref (info);
/* the name is owned by the info itself */
g_hash_table_insert (self->priv->app_id_to_app, (char*)shell_app_info_get_id (info),
info);
* Return value: (transfer full): The #ShellAppInfo for id, or %NULL if none
*/
ShellAppInfo *
-shell_app_system_lookup_app (ShellAppSystem *self, const char *id)
+shell_app_system_lookup_cached_app (ShellAppSystem *self, const char *id)
+{
+ ShellAppInfo *info;
+
+ info = g_hash_table_lookup (self->priv->app_id_to_app, id);
+ if (info)
+ shell_app_info_ref (info);
+ return info;
+}
+
+ShellAppInfo *
+shell_app_system_load_from_desktop_file (ShellAppSystem *system,
+ const char *filename,
+ GError **error)
{
- GMenuTreeEntry *entry;
+ ShellAppInfo *appinfo;
+ GKeyFile *keyfile;
+ char *full_path = NULL;
+ gboolean success;
+
+ keyfile = g_key_file_new ();
+
+ if (strchr (filename, '/') != NULL)
+ {
+ success = g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, error);
+ full_path = g_strdup (filename);
+ }
+ else
+ {
+ char *app_path = g_build_filename ("applications", filename, NULL);
+ success = g_key_file_load_from_data_dirs (keyfile, app_path, &full_path,
+ G_KEY_FILE_NONE, error);
+ g_free (app_path);
+ }
+
+ if (!success)
+ {
+ g_key_file_free (keyfile);
+ g_free (full_path);
+ return NULL;
+ }
+
+ appinfo = shell_app_info_new_from_keyfile_take_ownership (keyfile, full_path);
+ g_free (full_path);
- entry = g_hash_table_lookup (self->priv->app_id_to_app, id);
- if (entry)
- gmenu_tree_item_ref ((GMenuTreeItem*) entry);
- return (ShellAppInfo*)entry;
+ return appinfo;
}
/**
char *tmpid;
ShellAppInfo *result;
- result = shell_app_system_lookup_app (system, name);
+ result = shell_app_system_lookup_cached_app (system, name);
if (result != NULL)
return result;
* prefix. So try stripping them.
*/
tmpid = g_strjoin ("", "gnome-", name, NULL);
- result = shell_app_system_lookup_app (system, tmpid);
+ result = shell_app_system_lookup_cached_app (system, tmpid);
g_free (tmpid);
if (result != NULL)
return result;
tmpid = g_strjoin ("", "fedora-", name, NULL);
- result = shell_app_system_lookup_app (system, tmpid);
+ result = shell_app_system_lookup_cached_app (system, tmpid);
g_free (tmpid);
if (result != NULL)
return result;
const char *
shell_app_info_get_id (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_desktop_file_id ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return gmenu_tree_entry_get_desktop_file_id ((GMenuTreeEntry*)info->entry);
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return info->keyfile_path;
+ }
+ g_assert_not_reached ();
+ return NULL;
}
-const char *
+#define DESKTOP_ENTRY_GROUP "Desktop Entry"
+
+char *
shell_app_info_get_name (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_name ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return g_strdup (gmenu_tree_entry_get_name ((GMenuTreeEntry*)info->entry));
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Name", NULL, NULL);
+ }
+ g_assert_not_reached ();
+ return NULL;
}
-const char *
+char *
shell_app_info_get_description (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return g_strdup (gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info->entry));
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Comment", NULL, NULL);
+ }
+ g_assert_not_reached ();
+ return NULL;
}
-const char *
+char *
shell_app_info_get_executable (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return g_strdup (gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info->entry));
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return g_key_file_get_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Exec", NULL);
+ }
+ g_assert_not_reached ();
+ return NULL;
}
-const char *
+char *
shell_app_info_get_desktop_file_path (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return g_strdup (gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)info->entry));
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return g_strdup (info->keyfile_path);;
+ }
+ g_assert_not_reached ();
+ return NULL;
}
GIcon *
shell_app_info_get_icon (ShellAppInfo *info)
{
- const char *iconname;
+ char *iconname;
GIcon *icon;
/* This code adapted from gdesktopappinfo.c
* LGPL
*/
- iconname = gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ iconname = g_strdup (gmenu_tree_entry_get_icon ((GMenuTreeEntry*)info->entry));
+ break;
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ iconname = g_key_file_get_locale_string (info->keyfile, DESKTOP_ENTRY_GROUP, "Icon", NULL, NULL);
+ break;
+ }
+
if (!iconname)
return NULL;
icon = g_themed_icon_new (tmp_name);
g_free (tmp_name);
}
+ g_free (iconname);
+
return icon;
}
gboolean
shell_app_info_get_is_nodisplay (ShellAppInfo *info)
{
- return gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry*)info);
+ switch (info->type)
+ {
+ case SHELL_APP_INFO_TYPE_ENTRY:
+ return gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry*)info);
+ case SHELL_APP_INFO_TYPE_DESKTOP_FILE:
+ return FALSE;
+ }
+ g_assert_not_reached ();
+ return TRUE;
}
/**
if (!icon)
{
ret = clutter_texture_new ();
- g_object_set (ret, "width", size, "height", size, NULL);
+ g_object_set (ret, "opacity", 0, "width", size, "height", size, NULL);
return ret;
}
GError **error)
{
GDesktopAppInfo *gapp;
- const char *filename;
+ char *filename;
GdkAppLaunchContext *context;
gboolean ret;
ShellGlobal *global;
if (startup_id)
*startup_id = NULL;
- filename = gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*) info);
-
+ filename = shell_app_info_get_desktop_file_path (info);
gapp = g_desktop_app_info_new_from_filename (filename);
+ g_free (filename);
+
if (!gapp)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Not found");